/**
 ***********************************************************************************************************************
 * Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * @file        opencc_GSM7.c
 *
 * @brief       Other character coding types converte to GSM 7 bit coding or 
 *              GSM 7 bit encoding converts to other character coding types.
 *
 * @revision
 * Date         Author          Notes
 * 2020-11-20   OneOS Team      First Version
 ***********************************************************************************************************************
 */

 //Default Alphabet character table and extension character table is from 3GPP TS 23.038 version 10.0.0 Release 10

#include "opencc_GSM7.h"

static const unsigned short cc_GSM7_default_tbl[128] = {
    0x40, 0xA3, 0x24, 0xA5, 0xE8, 0xE9, 0xF9, 0xEC,
    0xF2, 0xC7, 0x0A, 0xD8, 0xF8, 0x0D, 0xC5, 0xE5,
    0x394, 0x5F, 0x3A6, 0x393, 0x39B, 0x3A9, 0x3A0, 0x3A8,
    0x3A3, 0x398, 0x39E, 0x1B, 0xC6, 0xE6, 0xDF, 0xC9,
    0x20, 0x21, 0x22, 0x23, 0xA4, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
    0xA1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
    0x58, 0x59, 0x5A, 0xC4, 0xD6, 0xD1, 0xDC, 0xA7,
    0xBF, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
    0x78, 0x79, 0x7A, 0xE4, 0xF6, 0xF1, 0xFC, 0xE0,
};

static const cc_GSM7_extern_map_t cc_GSM7_extern_tbl[] = {
    {0x0A, 0x0A},
    {0x14, 0x5E},
    {0x1B, 0x20},
    {0x28, 0x7B},
    {0x29, 0x7D},
    {0x2F, 0x5C},
    {0x3C, 0x5B},
    {0x3D, 0x7E},
    {0x3E, 0x5D},
    {0x40, 0x7C},
    {0x65, 0x20AC},
};

static int cc_GSM7_to_unicode(const void *in, unsigned size, unsigned long *val)
{
    const unsigned char *pin = (const unsigned char *)in;
    unsigned int ch1 = 0;
    unsigned int ch2 = 0;
    int i = 0;
    
    if (size < 1)
    {
        *val = 0;
        return 0;
    }

    ch1 = *pin++;
    if (ch1 >= 0x80)
    {
        *val = 0xFFFFFFFF;
        return 1;
    }

    
    if (ch1 != CC_GSM7_EXTERN_SIGN) /* when 2 Bytes， the first Byte is 0x1B */
    {
        *val = cc_GSM7_default_tbl[ch1];
        return 1;
    }

    if (size < 2)
    {
        *val = 0;
        return 1;
    }
    
    ch2 = *pin++;
    for (i = 0; i < CC_CMP_TABLE_SIZE(cc_GSM7_extern_tbl); i++)
    {
        if (ch2 == cc_GSM7_extern_tbl[i].GSM7)
        {
            *val = cc_GSM7_extern_tbl[i].asc2;
            return 2;
        }
    }

    *val = 0xFFFFFFFF;
    return 1;
}

static int cc_GSM7_from_unicode(unsigned long val, void *out, unsigned size)
{
    unsigned char *pout = (unsigned char *)out;
    int i = 0;
    
    if (val == CC_GSM7_EXTERN_SIGN) /*0x1b is wrong, 0x1b1b is right*/
    {
        return -1;
    }
    
    for (i = 0; i < CC_CMP_TABLE_SIZE(cc_GSM7_default_tbl); i++)
    {
        if (val == cc_GSM7_default_tbl[i])
        {
            if (pout != NULL && size >= 1)
            {
                *pout++ = i;
            }
            return 1;
        }
    }
    
    for (i = 0; i < CC_CMP_TABLE_SIZE(cc_GSM7_extern_tbl); i++)
    {
        if (val == cc_GSM7_extern_tbl[i].asc2)
        {
            if (pout != NULL && size >= 2)
            {
                *pout++ = CC_GSM7_EXTERN_SIGN;
                *pout++ = cc_GSM7_extern_tbl[i].GSM7;
            }
            return 2;
        }
    }
    
    return -1;
}

static cc_charc_set_t cc_GSM7_set_entry = {
    .charc_type = CC_CHARC_TYPE_GSM7,
    .min = 1,
    .max = 1,
    .unknown_char = '?',
    .charc_set_to_unicode = cc_GSM7_to_unicode,
    .unicode_to_charc_set = cc_GSM7_from_unicode,
};

cc_charc_set_t *cc_GSM7_get_entry(void)
{
    return &cc_GSM7_set_entry;
}



